package com.freemodbus4j.core.frame;

import com.freemodbus4j.core.exception.ModbusSlaveCodeEnum;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;

@Setter
@Getter
public class ModbusFrame {

    /**
     * 读取的消息长度
     */
    private int readLength;

    public int getReadLength() {
        return readLength;
    }

    public void setReadLength(int readLength) {
        this.readLength = readLength;
    }

    @Setter
    @Getter
    @Builder
    public static class RequestBody {
        /**
         * 功能码                寄存器PLC地址
         * 01读线圈状态          00001~09999
         * 02读离散输入状态      10001~19999
         * 03读保持寄存器       40001~49999
         * 04读输入寄存器       30001~39999
         * 05读单个线圈        00001~09999
         * 06写单个保持寄存器   40001~49999
         * 15写多个线圈        00001~09999
         * 16写多个保持寄存器   40001~49999
         */
        private byte func;

        private short childFunc;

        /**
         * modbus起始地址
         */
        private short address;

        /**
         * 读取寄存器个数
         */
        private short quantity;

        /**
         * 字节数 15(0x0F) 16(0x10)
         */
        private byte byteCount;

        /**
         * 变更数据 15(0x0F) 16(0x10)
         */
        private byte[] writeData;

        public byte[] getbodyBytes(byte[] readBytes, int startIndex) {
            readBytes[startIndex + 1] = func;
            switch (func) {
                case 1:
                case 2:
                case 3:
                case 4: {
                    readBytes[startIndex + 2] = (byte) (address >> 8 & 0xFF);
                    readBytes[startIndex + 3] = (byte) (address & 0xFF);
                    readBytes[startIndex + 4] = (byte) (quantity >> 8 & 0xFF);
                    readBytes[startIndex + 5] = (byte) (quantity & 0xFF);
                }
                break;
                case 5:
                case 6: {
                    readBytes[startIndex + 2] = (byte) (address >> 8 & 0xFF);
                    readBytes[startIndex + 3] = (byte) (address & 0xFF);
                    readBytes[startIndex + 4] =  writeData[0];
                    readBytes[startIndex + 5] = writeData[1];
                }
                break;
                case 8: {
                    readBytes[2] = (byte) (childFunc >> 8 & 0xFF);
                    readBytes[3] = (byte) (childFunc & 0xFF);
                    readBytes[startIndex + 4] =  writeData[0];
                    readBytes[startIndex + 5] = writeData[1];
                }
                break;
                case 11:
                case 12:
                    break;
                case 15:
                case 16: {
                    readBytes[startIndex + 2] = (byte) (address >> 8 & 0xFF);
                    readBytes[startIndex + 3] = (byte) (address & 0xFF);
                    readBytes[startIndex + 4] = (byte) (quantity >> 8 & 0xFF);
                    readBytes[startIndex + 5] = (byte) (quantity & 0xFF);
                    readBytes[startIndex + 6] = byteCount;
                    for (int i = 0; i < byteCount; i++) {
                        readBytes[startIndex + 7 + i] = writeData[i];
                    }
                }
                break;
                case 17:
                    break;
                default:
                    break;
            }
            return readBytes;
        }
    }

    @Setter
    @Getter
    @Builder
    public static class ResponseBody {
        private byte func;

        /**
         * 返回数据的字节数
         */
        private byte returnLength;

        /**
         * 读取寄存器个数
         */
        private byte[] data;

        private short inAddress;

        private byte[] inData;

        private short registerCount;

    }

    public static class Header {


        public byte[] getHeaderBytes() {
            return new byte[]{};
        }
    }

    @Setter
    @Getter
    @Builder
    public static class Except {

        private byte func;

        private ModbusSlaveCodeEnum exceptCode;

    }
}

